﻿Imports System.Reflection

Public Module ReflectionUtilities

    Friend Function GetAttribute(Of AttributeType)(ByVal type As Type) As AttributeType

        Dim Attributes As AttributeType() = type.GetCustomAttributes(GetType(AttributeType), False)
        If Attributes.Length = 0 Then
            Return Nothing
        Else
            Return Attributes(0)
        End If

    End Function

    Friend Function GetAttribute(Of AttributeType)(ByVal propertyInfo As PropertyInfo) As AttributeType

        Dim Attributes As AttributeType() = propertyInfo.GetCustomAttributes(GetType(AttributeType), False)
        If Attributes.Length = 0 Then
            Return Nothing
        Else
            Return Attributes(0)
        End If

    End Function

    Friend Function GetEntityFields(ByVal type As Type) As PropertyInfo()

        Dim Result As New List(Of PropertyInfo)

        For Each PropertyInfo As PropertyInfo In type.GetProperties
            Dim FieldLabel As FieldAttribute = GetAttribute(Of FieldAttribute)(PropertyInfo)
            If FieldLabel IsNot Nothing Then Result.Add(PropertyInfo)
        Next

        Return Result.ToArray

    End Function

    Friend Function ConvertValue(ByVal value As Object, ByVal type As Type) As Object

        ' When converting an empty string to a numberic type, return 0
        If TypeOf value Is String AndAlso DirectCast(value, String) = String.Empty Then
            If TypeIsNumericType(type) Then Return 0
        End If

        ' When converting an empty string to a date, return a 'null' date
        If TypeOf value Is String AndAlso DirectCast(value, String) = String.Empty Then
            If type Is GetType(DateTime) Then Return DateTime.MinValue
        End If

        ' When converting a null value, use the default value
        If value Is Nothing AndAlso type Is GetType(String) Then Return String.Empty
        If value Is Nothing Then Return Activator.CreateInstance(type)

        ' Handle all other cases
        Return Convert.ChangeType(value, type)

    End Function

    Public Function TypeIsWholeNumberType(ByVal type As Type) As Boolean

        Return type Is GetType(Int64) OrElse _
               type Is GetType(Int32) OrElse _
               type Is GetType(Int16) OrElse _
               type Is GetType(UInt64) OrElse _
               type Is GetType(UInt32) OrElse _
               type Is GetType(UInt16) OrElse _
               type Is GetType(Byte)

    End Function

    Public Function TypeIsNumericType(ByVal type As Type) As Boolean

        Return TypeIsWholeNumberType(type) OrElse _
               type Is GetType(Single) OrElse _
               type Is GetType(Double)

    End Function

End Module
